package com.corner.model.cornerservice.helper;

import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.sdk.android.oss.model.OSSException;
import com.corner.R;
import com.corner.app.App;
import com.corner.model.cornerservice.domain.CloudFile;
import com.corner.model.cornerservice.domain.GeoPoint;
import com.corner.model.cornerservice.domain.Info;
import com.corner.model.cornerservice.domain.Like;
import com.corner.model.cornerservice.domain.User;
import com.corner.model.cornerservice.service.Service;
import com.corner.model.cornerservice.service.exception.BaseException;
import com.corner.model.cornerservice.utils.ServiceQuery;
import com.corner.model.cornerservice.utils.SubServiceQuery;
import com.corner.model.oss.OSSManager;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.Subscriber;
import rx.schedulers.Schedulers;

/**
 * info的查询
 *
 * @author Administrator
 */
public class InfoHelper {

    private static final String UPDATED_AT = "updateAt";

    /**
     * 获取同感人数 通过result返回数量
     *
     * @param info
     */
    public static Observable<Long> getLikeUserCount(final Info info) {
        return Observable.create(new Observable.OnSubscribe<Long>() {
            @Override
            public void call(Subscriber<? super Long> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Like.INFO, info.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.equal(Like.TYPE, Like.LIKED, ServiceQuery.PROPERTY);
                    subscriber.onNext(Service.getInstance().likeService
                            .count(query.toString()).get(Service.COUNT));
                } catch (BaseException e) {
                    if (e.getCode().equals(BaseException.QueryNoResult)){
                        subscriber.onNext(0L);
                    }else{
                        subscriber.onError(e);
                    }
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 获取同感人 通过result返回like集合
     *
     * @param info
     */
    public static Observable<List<Like>> getLikeUsers(final Info info) {


        return Observable.create(new Observable.OnSubscribe<List<Like>>() {
            @Override
            public void call(Subscriber<? super List<Like>> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Like.INFO, info.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.equal(Like.TYPE, Like.LIKED, ServiceQuery.PROPERTY);
                    subscriber.onNext(Service.getInstance().likeService
                            .list(query.toString()));
                } catch (BaseException e) {
                    e.printStackTrace();
                    subscriber.onError(new Throwable(App.application.getString(R.string.request_data_error)));
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 获取阅读的人数。 通过result返回数量
     *
     * @param info
     */
    public static Observable<List<Like>> getReadedUsers(final Info info) {

        return Observable.create(new Observable.OnSubscribe<List<Like>>() {
            @Override
            public void call(Subscriber<? super List<Like>> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Like.INFO, info.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subscriber.onNext(Service.getInstance().likeService
                            .list(query.toString()));
                } catch (BaseException e) {
                    e.printStackTrace();
                    subscriber.onError(new Throwable(App.application.getString(R.string.request_data_error)));
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 获取阅读的人。 通过result返回like集合
     *
     * @param info
     */
    public static Observable<Long> getReadedUserCount(final Info info) {

        return Observable.create(new Observable.OnSubscribe<Long>() {
            @Override
            public void call(Subscriber<? super Long> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Like.INFO, info.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subscriber.onNext(Service.getInstance().likeService
                            .count(query.toString()).get(Service.COUNT));
                } catch (BaseException e) {
                    if (e.getCode().equals(BaseException.QueryNoResult)){
                        subscriber.onNext(0L);
                    }else{
                        subscriber.onError(e);
                    }
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 返回的result是Like对象，若为空，没有同感。
     *
     * @param info
     * @param user
     */
    public static Observable<Like> getLike(final Info info, final User user) {
        return Observable.create(new Observable.OnSubscribe<Like>() {
            @Override
            public void call(Subscriber<? super Like> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Like.INFO, info.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.equal(Like.USER, user.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.setLimit(1);
                    List<Like> list = Service.getInstance().likeService.list(query.toString());
                    if (list != null && list.size() > 0) {
                        subscriber.onNext(list.get(0));
                    } else
                        subscriber.onNext(null);
                } catch (BaseException e) {
                    if (e.getCode().equals(BaseException.QueryNoResult)){
                        subscriber.onNext(null);
                    }else {
                        subscriber.onError(e);
                    }
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 标记为已读/同感 返回like对象
     *
     * @param info
     * @param user
     */
    public static Observable<Like> readOrLikeOrNotSee(final Info info, final User user,
                                                      final int type) {

        return Observable.create(new Observable.OnSubscribe<Like>() {
            @Override
            public void call(Subscriber<? super Like> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Like.INFO, info.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.equal(Like.USER, user.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.setLimit(1);
                    List<Like> list = Service.getInstance().likeService.list(query.toString());
                    Like like;
                    if (list != null && list.size() > 0) {
                        like = list.get(0);
                        like.setType(type);
                        Service.getInstance().likeService.update(like.getObjectId(), like);
                    } else {
                        // 未读保存
                        like = new Like();
                        like.setInfo(info);
                        like.setUser(user);
                        like.setType(type);
                        Service.getInstance().likeService.save(like);
                    }
                    subscriber.onNext(like);
                    subscriber.onCompleted();
                } catch (BaseException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 发送info
     */
    public static Observable<Info> sendInfoIntoInfoTask(final Info info) {

        return Observable.create(new Observable.OnSubscribe<Info>() {
            @Override
            public void call(Subscriber<? super Info> subscriber) {
                 SendInfoTask.getInstance().addInfoTask(info);
                subscriber.onNext(info);
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 发送info
     */
    public static Observable<Info> sendInfo(final Info info) {

        return Observable.create(new Observable.OnSubscribe<Info>() {
            @Override
            public void call(Subscriber<? super Info> subscriber) {
                try {
                    if (!TextUtils.isEmpty(info.getAudioPath())) {
                        CloudFile upload = OSSManager.upload(info.getAudioPath());
                        info.setAudio(upload);
                    }
                    if (!TextUtils.isEmpty(info.getImagePath())) {
                        CloudFile upload = OSSManager.upload(info.getImagePath(), info.getScale());
                        info.setImage(upload);
                    }
                    Map<String, Object> map = Service.getInstance().infoService.save(info);
                    JSONObject jsonObject = new JSONObject(map);
                    info.setObjectId(jsonObject.getLong(Service.OBJECT_ID));
                    subscriber.onNext(info);
                } catch (IOException | BaseException | OSSException e) {
                    e.printStackTrace();
                    subscriber.onError(new Throwable());
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 删除信息，返回被删除的Info
     *
     * @param info
     */
    public static Observable<Info> deleteInfo(final Info info) {
        return Observable.create(new Observable.OnSubscribe<Info>() {
            @Override
            public void call(Subscriber<? super Info> subscriber) {
                try {
                    Service.getInstance().infoService.delete(info.getObjectId());
                    subscriber.onNext(info);
                } catch (BaseException e) {
                    subscriber.onError(new Throwable(App.application.getString(R.string.request_data_error)));
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }


    /**
     * 获取矩形区域内Info
     *
     * @param geoLB 西南方（屏幕左下角）坐标点
     * @param geoRT 东北方（屏幕右上角）坐标点
     * @param limit 限制
     * @param skip
     */
    public static Observable<List<Info>> getNearInfos(final GeoPoint geoLB, final GeoPoint geoRT,
                                                      final int limit, final int skip) {
        return Observable.create(new Observable.OnSubscribe<List<Info>>() {
            @Override
            public void call(Subscriber<? super List<Info>> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.inBorder(Info.GEO_POINT, geoLB, geoRT);
                    query.setLimit(limit);
                    query.setLastId(skip);
                    // 按修改时间降序排列
                    query.descenderBy(UPDATED_AT);
                    SubServiceQuery subServiceQuery = new SubServiceQuery();
                    subServiceQuery.setClassName(Like.class.getSimpleName());
                    subServiceQuery.setKey(Like.INFO);
                    subServiceQuery.setSelectType(SubServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.USER, User.getCurrentUser().getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.TYPE, Like.NOT_SEE, ServiceQuery.PROPERTY);
                    query.notIn(Service.OBJECT_ID, subServiceQuery, ServiceQuery.PROPERTY);
                    List<Info> result = Service.getInstance().infoService.list(query.toString()
                    );
                    subscriber.onNext(result);
                } catch (BaseException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());

    }

    /**
     * 获取userId对应的Infos
     *
     * @param userId
     * @param limit
     * @param skip
     */
    public static Observable<List<Info>> getInfos(final Long userId,
                                                  final int limit, final int skip) {

        return Observable.create(new Observable.OnSubscribe<List<Info>>() {
            @Override
            public void call(Subscriber<? super List<Info>> subscriber) {
                try {

                    ServiceQuery query = new ServiceQuery();
                    query.setLimit(limit);
                    query.setLastId(skip);
                    // 按修改时间降序排列
                    query.descenderBy(UPDATED_AT);
                    query.equal(Info.USER, userId, ServiceQuery.FOREIGN_KEY);
                    SubServiceQuery subServiceQuery = new SubServiceQuery();
                    subServiceQuery.setClassName(Like.class.getSimpleName());
                    subServiceQuery.setKey(Like.INFO);
                    subServiceQuery.setSelectType(SubServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.USER, User.getCurrentUser().getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.TYPE, Like.NOT_SEE, ServiceQuery.PROPERTY);
                    query.notIn(Service.OBJECT_ID, subServiceQuery, ServiceQuery.PROPERTY);
                    List<Info> result = Service.getInstance().infoService.list(query.toString());
                    subscriber.onNext(result);
                } catch (BaseException e) {
                    subscriber.onError(new Throwable());
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * @param locationId
     * @param limit
     * @param skip
     */
    public static Observable<List<Info>> getLocationInfos(final Long locationId,
                                                          final int limit, final int skip) {

        return Observable.create(new Observable.OnSubscribe<List<Info>>() {
            @Override
            public void call(Subscriber<? super List<Info>> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.setLimit(limit);
                    query.setLastId(skip);
                    // 按修改时间降序排列
                    query.descenderBy(UPDATED_AT);
                    query.equal(Info.AREA, locationId, ServiceQuery.FOREIGN_KEY);
                    SubServiceQuery subServiceQuery = new SubServiceQuery();
                    subServiceQuery.setClassName(Like.class.getSimpleName());
                    subServiceQuery.setKey(Like.INFO);
                    subServiceQuery.setSelectType(SubServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.USER, User.getCurrentUser().getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.TYPE, Like.NOT_SEE, ServiceQuery.PROPERTY);
                    query.notIn(Service.OBJECT_ID, subServiceQuery, ServiceQuery.PROPERTY);
                    List<Info> result = Service.getInstance().infoService.list(query.toString());
                    subscriber.onNext(result);
                } catch (BaseException e) {
                    subscriber.onError(new Throwable());
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 获userId发布的消息数量
     *
     * @param userId
     */
    public static Observable<Long> getInfoCount(final Long userId) {
        return Observable.create(new Observable.OnSubscribe<Long>() {
            @Override
            public void call(Subscriber<? super Long> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Info.USER, userId, ServiceQuery.FOREIGN_KEY);
                    SubServiceQuery subServiceQuery = new SubServiceQuery();
                    subServiceQuery.setClassName(Like.class.getSimpleName());
                    subServiceQuery.setKey(Like.INFO);
                    subServiceQuery.setSelectType(SubServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.USER, User.getCurrentUser().getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.TYPE, Like.NOT_SEE, ServiceQuery.PROPERTY);
                    query.notIn(Service.OBJECT_ID, subServiceQuery, ServiceQuery.PROPERTY);
                    Long result = Service.getInstance().infoService.count(query.toString()).get(Service.COUNT);
                    subscriber.onNext(result);
                } catch (BaseException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 获userId发布的消息数量
     *
     * @param userId
     */
    public static Observable<Long> getPicCount(final Long userId) {
        return Observable.create(new Observable.OnSubscribe<Long>() {
            @Override
            public void call(Subscriber<? super Long> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Info.USER, userId, ServiceQuery.FOREIGN_KEY);
                    query.exist(Info.IMAGE, true, ServiceQuery.PROPERTY);
                    SubServiceQuery subServiceQuery = new SubServiceQuery();
                    subServiceQuery.setClassName(Like.class.getSimpleName());
                    subServiceQuery.setKey(Like.INFO);
                    subServiceQuery.setSelectType(SubServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.USER, User.getCurrentUser().getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.TYPE, Like.NOT_SEE, ServiceQuery.PROPERTY);
                    query.notIn(Service.OBJECT_ID, subServiceQuery, ServiceQuery.PROPERTY);
                    Long result = Service.getInstance().infoService.count(query.toString()).get(Service.COUNT);
                    subscriber.onNext(result);
                } catch (BaseException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 根据Id获取Info
     *
     * @param infoId
     */
    public static Observable<Info> getInfo(final Long infoId) {

        return Observable.create(new Observable.OnSubscribe<Info>() {
            @Override
            public void call(Subscriber<? super Info> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    SubServiceQuery subServiceQuery = new SubServiceQuery();
                    subServiceQuery.setClassName(Like.class.getSimpleName());
                    subServiceQuery.setKey(Like.INFO);
                    subServiceQuery.setSelectType(SubServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.USER, User.getCurrentUser().getObjectId(), ServiceQuery.FOREIGN_KEY);
                    subServiceQuery.equal(Like.TYPE, Like.NOT_SEE, ServiceQuery.PROPERTY);
                    query.notIn(Service.OBJECT_ID, subServiceQuery, ServiceQuery.PROPERTY);

                    Info result = Service.getInstance().infoService.get(infoId, query.toString());
                    subscriber.onNext(result);
                } catch (BaseException e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());

    }

}
